#include "StdAfx.h"
#include "VDataModel.h"
									
// VDataModel /////////////////////////////////////////////////////////////////

//
VDataModel::VDataModel(QObject *parent)
	:QAbstractItemModel(parent)
	,m_dataTable(NULL)
{
	m_dataTable = new VDataTable;
}

//
VDataModel::~VDataModel()
{
	delete m_dataTable;
}

//
void VDataModel::setNode(VTreeNode *node)
{
	//beginResetModel();
	m_dataTable->setNode(node);
	//endResetModel();
	reset();
	if (canFetchMore(QModelIndex()))
		fetchMore(QModelIndex());
}

//
QModelIndex VDataModel::index(int row, int column,const QModelIndex &parent) const
{
	//if (parent.isValid() && parent.column() != 0)
	//	return QModelIndex();

	if (!m_dataTable->dataRecordCount())
		return QModelIndex();

	VDataRecord *dataRecord = m_dataTable->dataRecord(row);
	if (!dataRecord)
		return QModelIndex();

	VDataField *dataField = dataRecord->dataField(column);
	if (!dataField)
		return QModelIndex();

	return createIndex(row, column, dataField);
}

//
VDataField *VDataModel::dataFieldFromIndex(const QModelIndex &index) const
{
	if (!index.isValid())
		return NULL;
		
	return static_cast<VDataField*>(index.internalPointer());
}

//
QModelIndex VDataModel::parent(const QModelIndex &index) const
{
	return QModelIndex();
}

//
int VDataModel::rowCount(const QModelIndex &parent) const
{
	return m_dataTable->dataRecordCount();
}

//
int VDataModel::columnCount(const QModelIndex &parent) const
{
	return m_dataTable->dataFieldCount();
}

//
Qt::ItemFlags VDataModel::flags(const QModelIndex &index) const
{
	if (!index.isValid())
		return 0;

	return Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable;
}

//
QVariant VDataModel::headerData(int section,Qt::Orientation orientation,int role) const
{
	if (orientation == Qt::Horizontal)
	{
		VTreeNode *node = m_dataTable->node();
		if (!node)
			return QVariant();

		if (section >= node->childCount())
			return QVariant();

		VTreeNode *childNode = node->child(section);
		
		switch (role)
		{
			case Qt::DisplayRole:
				return childNode->item()->name();
		}
	}

	if (orientation == Qt::Vertical)
	{
		if (!m_dataTable->dataRecordCount())
			return QVariant();
		
		switch (role)
		{
			case Qt::DisplayRole:
				return m_dataTable->dataRecord(section)->idRec();

			case Qt::TextAlignmentRole:
				return int(Qt::AlignRight	|	Qt::AlignVCenter);
		}
	}
	
	return QVariant();
}

//
QVariant VDataModel::data(const QModelIndex &index, int role) const
{
	if (!index.isValid())
		return QVariant();

	int column = index.column();

	if (column < 0 || column >= m_dataTable->dataFieldCount())
		return QVariant();

	VDataField *dataField = dataFieldFromIndex(index);

	switch (role)
	{
		case Qt::DisplayRole:
		{
			if (dataField->isNull())
				return QVariant();
				
			return dataField->value();
		}
		break;

		case Qt::EditRole:
		{
			return dataField->value();
		}
		break;
	}
	
	return QVariant();
}

//
bool VDataModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
	if (role != Qt::EditRole)
		return false;

	VTreeNode *node = m_dataTable->node();
	if (!node)
		return false;

	VDataField *dataField = dataFieldFromIndex(index);
	bool isOk = false;
	dataField->setValue(value);

	VSqlDatabase db;
	db.transaction();

	int idRec = m_dataTable->dataRecord(index.row())->idRec();
	VTreeNode *nodeField = node->child(index.column());
	isOk = VDataSqlUpdateValue(db).exec(nodeField,idRec,dataField);

	if (isOk)
		db.commit();
	else
		db.rollback();

	if (isOk)
		emit dataChanged(index, index);

	return isOk;
}

//
bool VDataModel::insertRows(int position,int rows,const QModelIndex &parentIndex)
{
	VTreeNode *node = m_dataTable->node();
	if (!node)
		return false;

	VSqlDatabase db;
	db.transaction();

	VDataRecord record;
	bool isOk = VDataSqlInsertRecord(db).exec(node,record);

	if (isOk)
		db.commit();
	else
		db.rollback();

	if (!isOk)
		return false;

	beginInsertRows(parentIndex, position, position + rows - 1);
		m_dataTable->insertDataRecord(position,record);
	endInsertRows();

	return isOk;
}

//
bool VDataModel::removeRows(int position,int rows,const QModelIndex &parentIndex)
{
	VTreeNode *node = m_dataTable->node();
	if (!node)
		return false;

	VSqlDatabase db;
	db.transaction();

	QModelIndex posIndex = index(position,0, parentIndex);
	VDataField *posDataField = dataFieldFromIndex(posIndex);

	int idRec = m_dataTable->dataRecord(position)->idRec();
	bool isOk = VDataSqlDeleteRecord(db).exec(node,idRec);

	if (isOk)
		db.commit();
	else
		db.rollback();

	if (!isOk)
		return false;

	beginRemoveRows(parentIndex, position, position + rows - 1);
		m_dataTable->deleteDataRecord(position);
	endRemoveRows();

	return isOk;
}

//
bool VDataModel::canFetchMore(const QModelIndex &parent) const
{
	VTreeNode *node = m_dataTable->node();
	if (!node)
		return false;

	if (m_dataTable->dataRecordCount())
		return false;

	return true;
}

//
void VDataModel::fetchMore(const QModelIndex &parent)
{
	VTreeNode *node = m_dataTable->node();
	if (!node)
		return;

	VSqlDatabase db;
	QList<VDataRecord*> records;
	bool isOk = VDataSqlSelectRecords(db).exec(node,records);
	if (!isOk)
		return;

	if (!records.count())		
		return;
		
	beginInsertRows(parent, 0, records.count()-1);
		m_dataTable->setDataRecord(records);
	endInsertRows();
}

//
bool VDataModel::hasChildren(const QModelIndex &parent) const
{
	return false;
}
